package com.powernode.service.impl;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.powernode.model.ProdEs;
import com.powernode.service.SearchService;
import org.apache.lucene.util.QueryBuilder;
import org.elasticsearch.index.query.MatchQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.sort.SortBuilder;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.core.SearchHit;
import org.springframework.data.elasticsearch.core.SearchHits;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.List;
import java.util.stream.Collectors;

/**
 * 内容:
 * 作者: cy
 */
@Service
public class SearchServiceImpl implements SearchService {


    @Autowired
    private ElasticsearchRestTemplate elasticsearchRestTemplate;

    /**
     * 根据标签id查询商品信息
     * 抽象 就是把像的东西 抽出来
     * 有变化的当做入参
     *
     * @param tagId
     * @param size
     * @param current
     * @return
     */
    @Override
    public Page<ProdEs> searchProdEsByTagId(Long tagId, Integer size, Integer current) {
        Page<ProdEs> prodEsPage = new Page<>(current, size);
        MatchQueryBuilder matchQuery = QueryBuilders.matchQuery("tagList", tagId);
        return query(prodEsPage, current, size, matchQuery, 0, null);
    }


    /**
     * 根据分类id检索商品
     *
     * @param cateGoryId
     * @param size
     * @param current
     * @return
     */
    @Override
    public Page<ProdEs> searchProdByCategoryId(Long cateGoryId, Integer size, Integer current) {
        Page<ProdEs> prodEsPage = new Page<>(current, size);
        MatchQueryBuilder matchQuery = QueryBuilders.matchQuery("categoryId", cateGoryId);
        return query(prodEsPage, current, size, matchQuery, 0, null);
    }


    /**
     * 根据关键字检索商品
     * 模糊查询
     * 高亮
     * 排序
     * 分页
     *
     * @param prodName
     * @param size
     * @param current
     * @param sort
     * @return
     */
    @Override
    public Page<ProdEs> searchProdByKeywords(String prodName, Integer size, Integer current, Integer sort) {
        Page<ProdEs> prodEsPage = new Page<>(current, size);
        if (!StringUtils.hasText(prodName)) {
            prodEsPage.setTotal(0L);
            return prodEsPage;
        }
        MatchQueryBuilder matchQuery = QueryBuilders.matchQuery("prodName", prodName);
        return query(prodEsPage, current, size, matchQuery, sort, prodName);
    }


    private SortBuilder mySort(Integer sort) {
        switch (sort) {
            case 0:
                // 综合 按照好评率 倒排
                return SortBuilders.fieldSort("positiveRating").order(SortOrder.DESC);
            case 1:
                // 销量 倒排
                return SortBuilders.fieldSort("soldNum").order(SortOrder.DESC);
            case 2:
                // 价格 正排
                return SortBuilders.fieldSort("price").order(SortOrder.ASC);
            default:
                return SortBuilders.fieldSort("positiveRating").order(SortOrder.DESC);
        }
    }


    private Page<ProdEs> query(Page<ProdEs> prodEsPage, Integer current, Integer size, MatchQueryBuilder matchQuery, Integer sort, String prodName) {

        NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();
        nativeSearchQueryBuilder.withQuery(matchQuery);
        nativeSearchQueryBuilder.withPageable(PageRequest.of(current - 1, size));
        nativeSearchQueryBuilder.withSort(mySort(sort));
        if (StringUtils.hasText(prodName)) {
            HighlightBuilder.Field field = new HighlightBuilder.Field("prodName");
            field.preTags("<i style='color:red'>");
            field.postTags("</i>");
            nativeSearchQueryBuilder.withHighlightFields(field);
        }

        SearchHits<ProdEs> searchHits = elasticsearchRestTemplate.search(nativeSearchQueryBuilder.build(), ProdEs.class);
        // 转移参数
        prodEsPage.setTotal(searchHits.getTotalHits());
        searchHits.forEach(searchHit -> {
            ProdEs prodEs = searchHit.getContent();
            List<String> searchHitHighlightField = searchHit.getHighlightField("prodName");
            if (!CollectionUtils.isEmpty(searchHitHighlightField)) {
                String newName = searchHitHighlightField.get(0);
                prodEs.setProdName(newName);
            }
        });
        prodEsPage.setRecords(searchHits.stream()
                .map(SearchHit::getContent)
                .collect(Collectors.toList()));
        return prodEsPage;
    }

}
